home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / WD8003E.ASM < prev    next >
Assembly Source File  |  1992-01-10  |  16KB  |  580 lines

  1. ;History:90,1
  2. version    equ    7
  3.  
  4.     include    defs.asm
  5.  
  6. ;  The following people have contributed to this code: David Horne, Eric
  7. ;  Henderson, Bob Clements, and Jan Engvald LDC.
  8.  
  9. ;  Copyright, 1988-1992, Russell Nelson, Crynwr Software
  10.  
  11. ;   This program is free software; you can redistribute it and/or modify
  12. ;   it under the terms of the GNU General Public License as published by
  13. ;   the Free Software Foundation, version 1.
  14. ;
  15. ;   This program is distributed in the hope that it will be useful,
  16. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;   GNU General Public License for more details.
  19. ;
  20. ;   You should have received a copy of the GNU General Public License
  21. ;   along with this program; if not, write to the Free Software
  22. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. code    segment    byte public
  25.     assume    cs:code, ds:code
  26.  
  27. ; Stuff specific to the Western Digital WD8003E Ethernet controller board
  28. ; C version by Bob Clements, K1BC, May 1988 for the KA9Q TCP/IP package
  29.  
  30. ; The EN registers - First, the board registers
  31.  
  32. EN_CMD        equ    000h    ; Board's command register
  33. EN_REG1        equ    001h    ; 8013 bus size register
  34. EN_REG5        equ    005h    ; New command register (REGISTER 5)
  35. EN_SAPROM    equ    008h    ; Window on station addr prom
  36. EN_REGE        equ    00eh    ; Board Id (code) byte
  37.  
  38. EN_OFF        equ    10h
  39.  
  40. ENDCFG_BM8    equ    48h
  41.  
  42.     include    8390.inc
  43.  
  44. ; Board commands in EN_CMD
  45. EN_RESET    equ    080h    ; Reset the board
  46. EN_MEMEN    equ    040h    ; Enable the shared memory
  47. EN_MEM_MASK    equ    03fh    ; B18-B13 of address of the shared memory
  48.  
  49. ; Bits in REG1
  50. ENR1_BUS16BIT    equ    001h    ; Bus is 16 bits
  51.  
  52. ; Commands for REG5 register
  53. ENR5_MEM16EN    equ    080h    ; Enable 16 bit memory access from bus (8013)
  54. ENR5_LAN16EN    equ    040h    ; Enable 16 bit memory access from chip (8013)
  55. ENR5_MEM_MASK    equ    01fh    ; B23-B19 of address of the memory (8013)
  56. ENR5_LA19    equ    001h    ; B19 of address of the memory (8013)
  57. ENR5_EIL    equ    004h    ; Enable 8390 interrupts to bus (microchannel)
  58.  
  59. ; Bits in the REGE register
  60. ENRE_MICROCHANEL equ    080h    ; Microchannel bus (vs. PC/AT)
  61. ENRE_LARGERAM    equ    040h    ; Large RAM
  62. ENRE_SOFTCONFIG    equ    020h    ; Soft config
  63. ENRE_REVMASK    equ    01eh    ; Revision mask
  64. ENRE_ETHERNET    equ    001h    ; Ethernet (vs. Starlan)
  65.  
  66. ; Shared memory management parameters
  67.  
  68. SM_TSTART_PG    equ    0    ; First page of TX buffer
  69. SM_RSTART_PG    equ    6    ; Starting page of ring
  70. SM_RSTOP_PG    equ    32    ; Last page +1 of ring
  71.  
  72. ; End of WD8003E parameter definitions
  73.  
  74. board_features    db    0    ; Board features
  75. BF_MEM16EN    equ    1    ; 16-bit board, enable 16-bit memory
  76. BF_16K        equ    2    ; Board has 16 KB or shared memory
  77.  
  78. ram_enable    macro
  79.     endm
  80.  
  81.  
  82. reset_8390    macro
  83.     loadport        ; First, pulse the board reset
  84.     setport    EN_CMD
  85.     mov    al,EN_RESET        ;Turn on board reset bit
  86.     out    dx,al
  87.     longpause
  88.     xor    al,al            ;Turn off board reset bit
  89.     out    dx,al
  90.     setport    EN_REG5
  91.     mov    al,ENR5_EIL
  92.     test    sys_features,MICROCHANNEL
  93.     jz    reset_no_mc
  94.     out    dx,al            ; enable 8390 interrupts to bus
  95. reset_no_mc:
  96.     endm
  97.  
  98.  
  99. terminate_board    macro
  100.     endm
  101.  
  102. ; The following three values may be overridden from the command line.
  103. ; If they are omitted from the command line, these defaults are used.
  104.  
  105.     public    int_no, io_addr, mem_base
  106. int_no        db    3,0,0,0        ; Interrupt level
  107. io_addr        dw    0280h,0        ; I/O address for card (jumpers)
  108. mem_base    dw    0d000h,0    ; Shared memory addr (software)
  109.  
  110.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  111. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  112. driver_type    db    14        ;from the packet spec
  113. driver_name    db    'WD8003E',0    ;name of the driver.
  114. driver_function    db    2
  115. parameter_list    label    byte
  116.     db    1    ;major rev of packet driver
  117.     db    9    ;minor rev of packet driver
  118.     db    14    ;length of parameter list
  119.     db    EADDR_LEN    ;length of MAC-layer address
  120.     dw    GIANT    ;MTU, including MAC headers
  121.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  122.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  123.     dw    0    ;(# of successive xmits) - 1
  124. int_num    dw    0    ;Interrupt # to hook for post-EOI
  125.             ;processing, 0 == none,
  126.  
  127. is_186        db    0
  128.  
  129.     extrn    sys_features: byte
  130.  
  131. block_output:
  132. ;enter with cx = byte count, ds:si = buffer location, ax = buffer address
  133.     assume    ds:nothing
  134.     mov    es,mem_base        ; Set up ES:DI at the shared RAM
  135.     mov    di,ax            ; ..
  136. ; Can't use movemem which word aligns to the source, but needs to word
  137. ; align to the destination writing to WD8003ET/A. Fortunately works for
  138. ; all cards.
  139.     inc    cx        ; if odd bytes round up.
  140.     and    cx,not 1
  141.     call    rcopy_subr
  142.  
  143.     clc
  144.     ret            ; End of transmit-start routine
  145.  
  146. block_input:
  147. ;enter with cx = byte count, es:di = buffer location, ax = board address.
  148. ; Old version checked size, memory space, queue length here. Now done
  149. ; in higher level code.
  150. ; Set cx to length of this frame.
  151.     assume    ds:nothing,es:nothing
  152.     push    ds
  153.     mov    ds,mem_base        ; ds:si points at first byte to move
  154.     mov    si,ax
  155.  
  156.     cmp    cx,GIANT
  157.     jbe    rcv_size_ok        ; is the size sane? 
  158.     cmp    ch,cl            ; is it starlan bug (dup of low byte)
  159.     jz    rcv_starlan_bug
  160.     mov    cx,1514            ; cap the length
  161.     jmp    rcv_size_ok
  162. rcv_starlan_bug:            ; fix the starlan bug
  163.     mov    ch,ds:[si+EN_RBUF_NXT_PG] ; Page after this frame
  164.     cmp    ch,bl
  165.     ja    rcv_frm_no_wrap
  166.     add    ch,byte ptr cs:sm_rstop_ptr        ; Wrap if needed
  167.     dec    ch
  168. rcv_frm_no_wrap:
  169.     sub    ch,bl
  170.     dec    ch
  171. rcv_size_ok:
  172.  
  173.     add    ax,cx            ; Find the end of this frame.
  174.     cmp    ah,byte ptr cs:sm_rstop_ptr ; Over the top of the ring?
  175.     jb    rcopy_one_piece        ; Go move it
  176.  
  177. rcopy_wrap:
  178. ; Copy in two pieces due to buffer wraparound.
  179.     mov    ah,byte ptr cs:sm_rstop_ptr ; Compute length of first part
  180.     xor    al,al
  181.     sub    ax,si            ;  as all of the pages up to wrap point
  182.     sub    cx,ax            ; Move the rest in second part
  183.     push    cx            ; Save count of second part
  184.     mov    cx,ax            ; Count for first move
  185.     call    rcopy_subr
  186.     mov    si,SM_RSTART_PG*256    ; Offset to start of first receive page
  187.     pop    cx            ; Bytes left to move
  188. rcopy_one_piece:
  189.     call    rcopy_subr
  190.     pop    ds
  191.     ret
  192.  
  193.  
  194. rcopy_subr:
  195.     test    board_features,BF_MEM16EN; Is this a WD8013?
  196.     je    sm_wd8003        ; no, no need to enable 16-bit access.
  197.     loadport            ; Base of device
  198.     setport    EN_REG5            ; Enable 16-bit access
  199.     mov    al,ENR5_MEM16EN+ENR5_LAN16EN+ENR5_LA19
  200.     out    dx,al
  201.     shr    cx,1            ; convert byte count to word count
  202.     rep    movsw            ; Copy packet
  203.     mov    al,ENR5_LAN16EN+ENR5_LA19 ; Disable 16-bit access to WD8013
  204.     out    dx,al
  205.     jmp    short sm_copied
  206. sm_wd8003:
  207.     shr    cx,1            ; convert byte count to word count
  208.     rep    movsw
  209. sm_copied:
  210.     jnc    rcv_wrap_even        ; odd byte left over?
  211.     lodsw                ;   yes, word fetch
  212.     stosb                ;   and byte store
  213. rcv_wrap_even:
  214.     ret
  215.  
  216.  
  217.     include    8390.asm
  218.  
  219.     public    usage_msg
  220. usage_msg    db    "usage: WD8003E [-n] [-d] [-w] <packet_int_no> [-o] <int_level> <io_addr> <mem_base>",CR,LF,'$'
  221.  
  222.     public    copyright_msg
  223. copyright_msg    db    "Packet driver for Western Digital WD8003 E EBT EB ET/A and E/A, version "
  224.         db    '0'+majver,".",'0'+version,".",'0'+dp8390_version,CR,LF
  225.         db    "Portions Copyright 1988, Robert C. Clements, K1BC",CR,LF,'$'
  226.  
  227. no_board_msg    label    byte
  228.     db    "WD8003E apparently not present at this memory address.",CR,LF,'$'
  229. bad_cksum_msg    label    byte
  230.     db    "WD8003E not at this I/O address or address PROM bad.",CR,LF,'$'
  231. bad_board_msg    label    byte
  232.     db    "Suggested WD8003E memory address is invalid.",CR,LF,'$'
  233. occupied_msg    label    byte
  234.     db    "Suggested WD8003E memory address already occupied.",CR,LF,'$'
  235. using_16bits    db    "Accessing the board using 16 bits of data.",CR,LF,'$'
  236. int_no_name    db    "Interrupt number ",'$'
  237. io_addr_name    db    "I/O port ",'$'
  238. mem_base_name    db    "Memory address ",'$'
  239.  
  240. occupied_switch    db    0        ;if zero, don't use occupied test.
  241.  
  242.     extrn    set_recv_isr: near
  243.     extrn    skip_blanks: near
  244.  
  245. ;enter with si -> argument string, di -> word to store.
  246. ;if there is no number, don't change the number.
  247.     extrn    get_number: near
  248.  
  249. ;enter with dx -> name of word, di -> dword to print.
  250.     extrn    print_number: near
  251.  
  252.     public    parse_args
  253. parse_args:
  254.     call    skip_blanks
  255.     cmp    al,'-'            ;did they specify a switch?
  256.     jne    not_switch
  257.     cmp    byte ptr [si+1],'o'    ;did they specify '-o'?
  258.     je    got_occupied_switch
  259.     stc                ;no, must be an error.
  260.     ret
  261. got_occupied_switch:
  262.     mov    occupied_switch,1
  263.     add    si,2            ;skip past the switch's characters.
  264.     jmp    parse_args        ;go parse more arguments.
  265. not_switch:
  266. ; ** start of code added by Reinhard Strebler Universitaet Karlsruhe 1/10/91
  267.     test    sys_features,MICROCHANNEL
  268.     jnz    do_mc_defaults
  269.     jmp    just_parse_args
  270. do_mc_defaults:
  271.  
  272. ; channel selector resides at io 96h
  273. ; POS register base is at io 100h
  274. ; WD8003E ID is one of 6FC0h, 6FC1h or 6FC2h
  275. ; IBM Ethernet Adapter A is EFE5h
  276.  
  277. ; search thro' the slots for a wd8003e card
  278.     mov    cx, 8            ; for all channels(slots)
  279.  
  280. ; channel select value for slots 0,1,2.. is 8,9,A etc
  281. ; start with slot 0, and then 7,6,5,4,3,2,1
  282. get_05:
  283.     mov    ax, cx            ; channel number
  284.     or    ax, 08h         ; reg. select value
  285.     mov    dx, 96h         ; channel select register
  286.     out    dx, al            ; select channel
  287.  
  288. ; read adapter id
  289.     mov    dx, 101h
  290.     in    al, dx            ; adapter id - ms byte
  291.     mov    ah, al
  292.     dec    dx
  293.     in    al, dx            ; adapter id - ls byte
  294.  
  295. ; Check if wd8003e
  296.     cmp    ax, 06FC0h
  297.     je    get_10
  298.     cmp    ax, 06FC1h
  299.     je    get_10
  300.     cmp    ax, 06FC2h
  301.     je    get_10
  302. ; Check if IBM Ethernet Adapter A
  303.     cmp     ax, 0EFE5h
  304.     je      get_10
  305.     loop    get_05
  306.  
  307.     mov    dx,offset no_WD8003E_msg
  308.     mov    etopen_diagn,37
  309.     jmp    error_wrt
  310.  
  311. no_WD8003E_msg:
  312.     db    "WD8003E apparently not found.",CR,LF,'$'
  313.  
  314. int_xlate db    03,04,10,15
  315.  
  316. get_10:
  317. ; found our Adapter
  318.  
  319. ; Get WD8003E I/O Address ( read POS Register 0 )
  320.     xor    ax,ax
  321.     mov    dx,102h
  322.     in    al,dx
  323.     and    al,0FEh
  324.     mov    cl,4
  325.     shl    ax,cl
  326.     mov    io_addr,ax
  327. ; Get WD8003E shared RAM memory address (read POS Register 1 )
  328.     xor    ax,ax
  329.     mov    dx,103h
  330.     in    al,dx
  331.     and    al,0FCh
  332.     xchg    al,ah
  333.     mov    mem_base,ax
  334. ; Get WD8003E IRQ (read POS Register 1 )
  335.     xor    ax,ax
  336.     mov    dx,105h
  337.     in    al,dx
  338.     and    al,003h
  339.     mov    bx,offset int_xlate
  340.     xlat    cs:int_xlate
  341.     mov    int_no,al
  342. ; ** end of code added by Reinhard Strebler Universitaet Karlsruhe 1/10/91
  343.  
  344. just_parse_args:
  345.     mov    di,offset int_no
  346.     call    get_number
  347.     mov    di,offset io_addr
  348.     call    get_number
  349.     mov    di,offset mem_base
  350.     call    get_number
  351.     clc
  352.     ret
  353.  
  354.     extrn    etopen_diagn: byte
  355. addr_not_avail:
  356.     mov    dx,offset occupied_msg
  357.     mov    etopen_diagn,34
  358. bad_cksum:
  359.     mov    dx,offset bad_cksum_msg
  360.     mov    etopen_diagn,37
  361.     jmp    short error_wrt
  362. bad_memory:
  363.     mov    dx,offset bad_board_msg
  364.     mov    etopen_diagn,37
  365. no_memory:
  366.     mov    dx,offset no_board_msg
  367.     mov    etopen_diagn,37
  368. error_wrt:
  369.     mov    ah,9
  370.     int    21h
  371.     stc
  372.     ret
  373.  
  374.  
  375. init_card:
  376. ; Now get the board's physical address from on-board PROM into card_hw_addr
  377.     assume ds:code
  378.  
  379.     test    sys_features,MICROCHANNEL
  380.     jz    etopen_no_mc
  381.     or    board_features,BF_16K
  382.     or    endcfg,ENDCFG_WTS
  383.     loadport
  384.     setport    EN_REG5
  385.     mov    al,ENR5_EIL
  386.     out    dx,al        ; enable 8390 interrupts to bus
  387.     jmp    etopen_have_id
  388. etopen_no_mc:            ; Check for WD8013EBT
  389.     loadport        ; WD8013EBT doesn't have register alaasing
  390.     setport    EN_CMD        ; Register 0 may be aliased to Register 8
  391.     mov bx,    dx
  392.     setport    EN_SAPROM
  393.     mov cx,    EN_SAPROM-EN_CMD ; Check 8 bytes
  394. alias_loop:
  395.     in al,    dx        ; Get one register
  396.     mov ah,    al
  397.     xchg bx, dx        ; Switch to other register
  398.     in al,    dx        ; Get other register
  399.     cmp al,    ah        ; Are they the same?
  400.     jne    not_aliased    ; Nope, not aliased
  401.     inc    bx        ; Increment register pair
  402.     inc    dx
  403.     dec    cx        ; Decrement loop counter
  404.     jne    alias_loop    ; Finished?
  405.     jmp    etopen_have_id    ; Aliased; not WD8013EBT
  406. not_aliased:            ; Not aliased; Check for 16-bit board
  407.     loadport
  408.     setport    EN_REG1        ; Bit 0 must be unmodifiable
  409.     in al,    dx        ; Get register 1
  410.     mov bl,    al        ; Store original value
  411.     xor al,    ENR1_BUS16BIT    ; Flip bit 0
  412.     out dx,    al        ; Write it back
  413.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  414.     mov ah,    al        ; Store bit value
  415.     in al,    dx        ; Read register again
  416.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  417.     cmp al,    ah        ; Was it modified?
  418.     jne    board16bit    ; No; board is a WD8013EBT !
  419.     mov al,    bl        ; Get original value
  420.     out dx,    al        ; Write it back
  421.     jmp    etopen_have_id
  422. board16bit:            ; But is it plugged into a 16-bit slot?
  423.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  424.     je    etopen_have_id    ; Nope; silly board installer!
  425.     mov    dx,offset using_16bits
  426.     mov    ah,9
  427.     int    21h
  428.     or    board_features,BF_MEM16EN+BF_16K
  429.     or    endcfg,ENDCFG_WTS
  430.     loadport
  431.     setport    EN_REG5
  432.     mov    al,ENR5_LAN16EN+ENR5_LA19 ; Write LA19 now, but not MEM16EN
  433.     out    dx,al        ; enable 8390 interrupts to bus
  434.  
  435. etopen_have_id:
  436.  
  437.     loadport            ; base of device
  438.     setport    EN_SAPROM        ; Where the address prom is
  439.     cld                ; make sure string mode is right
  440.     push    cs            ; Point es:di at local copy space
  441.     pop    es
  442.     mov di,    offset curr_hw_addr
  443.     mov cx,    EADDR_LEN        ; Set count for loop
  444.     xor bx,    bx            ; Clear the addr ROM checksum
  445. ini_addr_loop:
  446.     in    al,dx            ; Get a byte of address
  447.     stosb                ; Feed it to caller
  448.     add    bl,al            ; Compute the checksum
  449.     inc    dx            ; Next byte at next I/O port
  450.     loop    ini_addr_loop        ; Loop over six bytes
  451.  
  452.     in al,    dx            ; Get seventh byte
  453.     add bl,    al            ; Add it in
  454.     inc    dx            ; Step to eighth byte
  455.     in al,    dx            ; Get last byte
  456.     add bl,    al            ; Final checksum
  457.     cmp bl, 0ffh            ; Correct?
  458.     je    good_cksum
  459.     jmp    bad_cksum        ; No, board is not happy
  460. good_cksum:
  461.  
  462. ; Check if the shared memory address range is available to us
  463.     mov    bx,mem_base
  464.     cmp    occupied_switch,0    ; did they insist?
  465.     jne    no_lim_chk        ; yes, don't check.
  466.     cmp    bh,080h            ; low limit is 8000
  467.     jae    fr_8000
  468.     jmp    bad_memory
  469. fr_8000:
  470.     cmp    bh,0f0h            ; upper limit is F000
  471.     jb    to_f000
  472.     jmp    bad_memory
  473. to_f000:
  474.     test    bx,01ffh        ; must be on a 8 k boundary
  475.     jz    eightk
  476.     jmp    bad_memory
  477. eightk:
  478. no_lim_chk:
  479.     mov    di,8*1024/16        ; 8 kbyte
  480.     mov    sm_rstop_ptr,32
  481.     test    board_features,BF_16K
  482.     jz    just_8k
  483.     mov    cx,16*1024/16        ; 16 kbytes
  484.     mov    sm_rstop_ptr,64
  485. just_8k:
  486.     cmp    occupied_switch,0    ; did they insist?
  487.     jne    is_avail        ; yes, don't check.
  488.     call    occupied_chk        ; check if address range is available
  489.     jnc    is_avail
  490.     jmp    addr_not_avail        ; we HAVE to have at least 8/16 kbyte
  491. is_avail:
  492.     test    board_features,BF_16K
  493.     jnz    not_32k
  494.     mov    di,32*1024/16        ; may be there is space for 32 kbyte
  495.     call    occupied_chk
  496.     jc    not_32k            ; no, then don't try it later either
  497.     and    bh,7
  498.     jnz    not_32k            ; must be on a 32k boundary
  499.     mov    sm_rstop_ptr,128    ; yes, there is space for a WD8003EBT
  500. not_32k:
  501.  
  502. ; Turn on the shared memory block
  503.     loadport
  504.     setport    EN_CMD        ; Point at board command register
  505.     mov ax,    mem_base    ; Find where shared memory will be mapped
  506.     mov al,    ah        ; Shift to right location
  507.     shr al,    1        ;  in the map control word
  508.     and al,    EN_MEM_MASK    ; Just these bits
  509.     or al,    EN_MEMEN    ; Command to turn on map
  510.     test    sys_features,MICROCHANNEL
  511.     jz    AT_card
  512.     mov    al,EN_MEMEN    ; membase handled different for MC card
  513. AT_card:
  514.     out dx,    al        ; Create that memory
  515.  
  516. ; Find how much memory this card has (without destroying other memory)
  517.     mov    si,ax            ; save bord command value
  518.     mov    es,mem_base
  519.     mov    bl,0FFh            ; first try 32 kbyte (WD8003EBT)
  520.     mov    bh,sm_rstop_ptr        ;   or what is available
  521.     dec    bh
  522. memloop:
  523.     dec    bx            ; use even address
  524.     cli                ; disable interrupts
  525.     mov    cx,es:[bx]        ; save old memory contents
  526.     mov    word ptr es:[bx],05A5Ah    ; put testpattern
  527.     loadport
  528.     setport    EN_CCMD            ; drain the board bus for any
  529.     in    al,dx            ;   capacitive memory
  530.     cmp    word ptr es:[bx],05A5Ah    ; any real memory there?
  531.     jne    not_our_mem        ;   no
  532.     setport    EN_CMD            ;   yes
  533.     mov    ax,si
  534.     and    al,0FFh xor EN_MEMEN
  535.     out    dx,al            ; turn off our memory
  536.     jmp    short $+2
  537.     or    al,EN_MEMEN
  538.     cmp    word ptr es:[bx],05A5Ah    ; was it OUR memory?
  539.     out    dx,al            ; turn on our memory.
  540.     jmp    short $+2
  541.     mov    es:[bx],cx        ; restore the original contents.
  542.     sti
  543.     jne    our_mem            ;   yes, it wasn't there any more
  544. not_our_mem:                ;   no, it was still there
  545.     shr    bx,1            ; test if half as much memory
  546.     cmp    bx,1FFFh        ; down to 8 kbyte
  547.     jae    memloop
  548.     jmp    no_memory        ; no memory at address mem_base
  549. our_mem:                ; it IS our memory!
  550.     inc    bh
  551.     mov    sm_rstop_ptr,bh        ; # of 256 byte ring bufs + 1
  552.     mov    ch,bh
  553.     xor    cl,cl
  554.     mov    ax,mem_base
  555.     call    memory_test        ; check all of that memory
  556.     je    mem_ok
  557.     jmp    no_memory
  558. mem_ok:
  559.     ret
  560.  
  561.     public    print_parameters
  562. print_parameters:
  563.     mov    di,offset int_no
  564.     mov    dx,offset int_no_name
  565.     call    print_number
  566.     mov    di,offset io_addr
  567.     mov    dx,offset io_addr_name
  568.     call    print_number
  569.     mov    di,offset mem_base
  570.     mov    dx,offset mem_base_name
  571.     call    print_number
  572.     ret
  573.  
  574.     include    memtest.asm
  575.     include    occupied.asm
  576.  
  577. code    ends
  578.  
  579.     end
  580.